package com.museyu.model;

import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class GameRoom {
    private String id;
    private List<Player> players;
    private String roomOwnerId;
    private Player currentDealer;
    private int currentPlayerIndex;
    private GameState state;
    private List<Card> deck = new ArrayList<>();
    private Set<String> drawnPlayers;
    private static final Logger logger = LoggerFactory.getLogger(GameRoom.class);
    private String ownerId;
    private String currentPlayerId;

    public enum GameState {
        WAITING,    // 等待玩家加入
        BIDDING,    // 抢庄阶段
        DEALING,    // 发牌阶段
        PLAYING,    // 游戏进行中
        ENDED       // 游戏结束
    }

    public GameRoom(String id) {
        this.id = id;
        this.players = new ArrayList<>();
        this.state = GameState.WAITING;
        this.drawnPlayers = new HashSet<>();
        initializeDeck();
    }

    public String getId() {
        return id;
    }

    public List<Player> getPlayers() {
        return players;
    }

    public GameState getState() {
        return state;
    }

    public void setState(GameState state) {
        this.state = state;
    }

    public void addPlayer(Player player) {
        if (players.isEmpty()) {
            ownerId = player.getId();
            logger.info("设置房主: playerId={}, roomId={}", player.getId(), id);
        }
        players.add(player);
    }

    public boolean removePlayer(String playerId) {
        boolean removed = players.removeIf(p -> p.getId().equals(playerId));
        if (removed && players.isEmpty()) {
            state = GameState.WAITING;
            currentDealer = null;
            currentPlayerIndex = 0;
            roomOwnerId = null;
        }
        return removed;
    }

    public boolean hasPlayers() {
        return !players.isEmpty();
    }

    public int getPlayerCount() {
        return players.size();
    }

    public boolean isRoomOwner(String playerId) {
        return roomOwnerId != null && roomOwnerId.equals(playerId);
    }

    public boolean hasDealer() {
        return currentDealer != null;
    }

    public Player getPlayerById(String playerId) {
        return players.stream()
                .filter(p -> p.getId().equals(playerId))
                .findFirst()
                .orElse(null);
    }

    public Player getCurrentPlayer() {
        if (players.isEmpty()) {
            return null;
        }
        return players.get(currentPlayerIndex);
    }

    public void nextPlayer() {
        if (players.isEmpty()) {
            return;
        }
        
        // 获取当前玩家的索引
        int currentIndex = -1;
        for (int i = 0; i < players.size(); i++) {
            if (players.get(i).getId().equals(currentPlayerId)) {
                currentIndex = i;
                break;
            }
        }
        
        if (currentIndex == -1) {
            return;
        }
        
        // 找到下一个未摸牌的玩家
        int nextIndex = (currentIndex + 1) % players.size();
        int startIndex = nextIndex;
        
        do {
            Player nextPlayer = players.get(nextIndex);
            if (!hasPlayerDrawn(nextPlayer.getId())) {
                currentPlayerId = nextPlayer.getId();
                logger.info("轮到下一个玩家: playerId={}, roomId={}", currentPlayerId, id);
                return;
            }
            nextIndex = (nextIndex + 1) % players.size();
        } while (nextIndex != startIndex);
        
        // 如果所有玩家都摸过牌了，结束游戏
        state = GameState.ENDED;
        logger.info("所有玩家已摸牌，游戏结束: roomId={}", id);
    }

    public void setCurrentDealer(Player dealer) {
        this.currentDealer = dealer;
    }

    private void initializeDeck() {
        deck.clear();
        String[] suits = {"♠", "♥", "♣", "♦"};
        String[] values = {"A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"};
        
        for (String suit : suits) {
            for (String value : values) {
                deck.add(new Card(suit, value));
            }
        }
        Collections.shuffle(deck);
    }

    public Card drawCard() {
        if (deck.isEmpty()) {
            return null;
        }
        return deck.remove(0);
    }

    public void dealInitialCards() {
        // 重置摸牌状态
        drawnPlayers.clear();
        // 设置初始玩家顺序（非庄家先开始）
        currentPlayerIndex = 0;
        for (int i = 0; i < players.size(); i++) {
            if (players.get(i).equals(currentDealer)) {
                currentPlayerIndex = (i + 1) % players.size();
                break;
            }
        }
        
        // 重新初始化牌组
        initializeDeck();
        
        // 给每个玩家发两张牌
        for (Player player : players) {
            player.getCards().clear();
            for (int i = 0; i < 2; i++) {
                Card card = drawCard();
                if (card != null) {
                    player.addCard(card);
                }
            }
            // 计算初始点数
            player.setPoints(calculatePoints(player.getCards()));
            logger.info("玩家初始点数: playerId={}, points={}, cards={}", 
                player.getId(), player.getPoints(), player.getCards());
        }
    }

    public boolean hasPlayerDrawn(String playerId) {
        return drawnPlayers.contains(playerId);
    }

    public void markPlayerDrawn(String playerId) {
        drawnPlayers.add(playerId);
        logger.info("玩家已摸牌: playerId={}, roomId={}", playerId, id);
    }

    public boolean allPlayersDrawn() {
        return drawnPlayers.size() == players.size();
    }

    public Map<String, Object> getPlayerView(String playerId) {
        Map<String, Object> view = new HashMap<>();
        view.put("state", state.name());
        
        // 添加调试日志
        logger.info("构建玩家视图 - 当前状态: state={}, currentPlayerId={}, players={}", 
            state, currentPlayerId, players.stream()
                .map(p -> String.format("{id=%s, name=%s, points=%d}", p.getId(), p.getName(), p.getPoints()))
                .collect(Collectors.joining(", ")));
        
        view.put("players", players.stream().map(p -> {
            Map<String, Object> playerView = new HashMap<>();
            playerView.put("id", p.getId());
            playerView.put("name", p.getName());
            playerView.put("isRoomOwner", isRoomOwner(p.getId()));
            playerView.put("isDealer", p.getId().equals(currentDealer != null ? currentDealer.getId() : null));
            
            // 明确设置布尔值
            boolean isCurrent = p.getId().equals(currentPlayerId);
            boolean hasDrawn = hasPlayerDrawn(p.getId());
            playerView.put("isCurrentPlayer", isCurrent);
            playerView.put("hasDrawn", hasDrawn);
            
            // 只有当前玩家可以看到自己的牌和点数
            if (p.getId().equals(playerId)) {
                playerView.put("cards", p.getCards());
                playerView.put("points", p.getPoints());
            } else {
                playerView.put("cards", Collections.nCopies(p.getCards().size(), new Card("?", "?")));
                playerView.put("points", null);
            }
            
            return playerView;
        }).collect(Collectors.toList()));
        
        return view;
    }

    private int calculatePoints(List<Card> cards) {
        int points = 0;
        for (Card card : cards) {
            String value = card.getValue();
            if (value.equals("A")) {
                points += 1;
            } else if (value.equals("J") || value.equals("Q") || value.equals("K")) {
                points += 10;
            } else {
                try {
                    points += Integer.parseInt(value);
                } catch (NumberFormatException e) {
                    // 忽略无效的牌值
                }
            }
        }
        return points;
    }

    public String getDealerId() {
        return currentDealer != null ? currentDealer.getId() : null;
    }

    public void setDealerId(String playerId) {
        if (state != GameState.BIDDING) {
            throw new IllegalStateException("当前不是抢庄阶段");
        }
        if (currentDealer != null) {
            throw new IllegalStateException("已有庄家");
        }
        
        Player player = getPlayerById(playerId);
        if (player == null) {
            throw new IllegalArgumentException("玩家不在房间中");
        }
        
        this.currentDealer = player;
        player.setDealer(true);
        
        // 设置游戏状态为发牌阶段
        state = GameState.DEALING;
        
        // 发初始牌
        dealInitialCards();
        
        // 设置游戏状态为游戏进行中
        state = GameState.PLAYING;
        
        // 设置第一个摸牌的玩家（非庄家优先）
        List<Player> nonDealerPlayers = players.stream()
            .filter(p -> !p.getId().equals(playerId))
            .collect(Collectors.toList());
        
        if (!nonDealerPlayers.isEmpty()) {
            currentPlayerId = nonDealerPlayers.get(0).getId();
            logger.info("设置第一个摸牌玩家: playerId={}, roomId={}, playerName={}", 
                currentPlayerId, id, nonDealerPlayers.get(0).getName());
        } else {
            currentPlayerId = players.get(0).getId();
            logger.info("没有非庄家玩家，设置庄家为第一个摸牌玩家: playerId={}, roomId={}, playerName={}", 
                currentPlayerId, id, players.get(0).getName());
        }
        
        logger.info("设置庄家成功: playerId={}, roomId={}", playerId, id);
    }

    public List<Card> getDeck() {
        return deck;
    }

    public void setDeck(List<Card> deck) {
        this.deck = deck;
    }

    public int getCurrentPlayerIndex() {
        return currentPlayerIndex;
    }

    public void setCurrentPlayerIndex(int currentPlayerIndex) {
        this.currentPlayerIndex = currentPlayerIndex;
    }

    public String getOwnerId() {
        return ownerId;
    }
    
    public void setOwnerId(String ownerId) {
        this.ownerId = ownerId;
    }
    
    public String getCurrentPlayerId() {
        return currentPlayerId;
    }
    
    public void setCurrentPlayerId(String currentPlayerId) {
        this.currentPlayerId = currentPlayerId;
    }
    
    public void startGame() {
        if (state != GameState.WAITING) {
            throw new IllegalStateException("游戏已经开始");
        }
        if (players.size() < 2) {
            throw new IllegalStateException("玩家数量不足");
        }
        
        // 开始游戏，进入抢庄阶段
        state = GameState.BIDDING;
    }
    
    public void drawCard(String playerId) {
        if (state != GameState.PLAYING) {
            throw new IllegalStateException("当前不是游戏阶段");
        }
        
        Player player = getPlayerById(playerId);
        if (player == null) {
            throw new IllegalArgumentException("玩家不在房间中");
        }
        
        // 检查是否是当前玩家的回合
        if (!currentPlayerId.equals(playerId)) {
            throw new IllegalStateException("不是你的回合");
        }
        
        // 检查玩家是否已经摸过牌
        if (hasPlayerDrawn(playerId)) {
            throw new IllegalStateException("你已经摸过牌了");
        }
        
        // 摸牌
        Card card = drawCard();
        if (card == null) {
            throw new IllegalStateException("牌堆已空");
        }
        
        player.addCard(card);
        // 重新计算点数
        player.setPoints(calculatePoints(player.getCards()));
        logger.info("玩家摸牌后点数: playerId={}, points={}, newCard={}, allCards={}", 
            playerId, player.getPoints(), card, player.getCards());
        
        markPlayerDrawn(playerId);
        
        // 如果所有玩家都摸过牌了，结束游戏
        if (allPlayersDrawn()) {
            state = GameState.ENDED;
            logger.info("所有玩家已摸牌，游戏结束: roomId={}", id);
        } else {
            // 轮到下一个玩家
            nextPlayer();
        }
    }

    public void skipTurn(String playerId) {
        if (state != GameState.PLAYING) {
            throw new IllegalStateException("当前不是游戏阶段");
        }
        
        Player player = getPlayerById(playerId);
        if (player == null) {
            throw new IllegalArgumentException("玩家不在房间中");
        }
        
        // 检查是否是当前玩家的回合
        if (!currentPlayerId.equals(playerId)) {
            throw new IllegalStateException("不是你的回合");
        }
        
        // 检查玩家是否已经摸过牌
        if (hasPlayerDrawn(playerId)) {
            throw new IllegalStateException("你已经摸过牌了");
        }
        
        // 标记玩家已摸牌（跳过也视为完成回合）
        markPlayerDrawn(playerId);
        logger.info("玩家跳过回合: playerId={}, roomId={}", playerId, id);
        
        // 如果所有玩家都摸过牌了，结束游戏
        if (allPlayersDrawn()) {
            state = GameState.ENDED;
            logger.info("所有玩家已摸牌，游戏结束: roomId={}", id);
        } else {
            // 轮到下一个玩家
            nextPlayer();
        }
    }
} 